apiVersion: templates.gatekeeper.sh/v1
kind: ConstraintTemplate
metadata:
  name: d8apparmor
  labels:
    heritage: deckhouse
    module: admission-policy-engine
    security.deckhouse.io: security-policy
  annotations:
    metadata.gatekeeper.sh/title: "App Armor"
    description: >-
      Configures an allow-list of AppArmor profiles for use by containers.
      This corresponds to specific annotations applied to a PodSecurityPolicy.
      For information on AppArmor, see
      https://kubernetes.io/docs/tutorials/clusters/apparmor/
spec:
  crd:
    spec:
      names:
        kind: D8AppArmor
      validation:
        # Schema for the `parameters` field
        openAPIV3Schema:
          type: object
          description: >-
            Configures an allow-list of AppArmor profiles for use by containers.
            This corresponds to specific annotations applied to a PodSecurityPolicy.
            For information on AppArmor, see
            https://kubernetes.io/docs/tutorials/clusters/apparmor/
          properties:
            allowedProfiles:
              description: "An array of AppArmor profiles. Examples: `runtime/default`, `unconfined`."
              type: array
              items:
                type: string
  targets:
    - target: admission.k8s.gatekeeper.sh
      rego: |
        package d8.security_policies

        violation[{"msg": msg, "details": {}}] {
            metadata := input.review.object.metadata
            container := input_containers[_]
            not input_apparmor_allowed(container, metadata)
            msg := sprintf("AppArmor profile is not allowed, pod: %v, container: %v. Allowed profiles: %v", [input.review.object.metadata.name, container.name, input.parameters.allowedProfiles])
        }

        input_apparmor_allowed(container, metadata) {
            glob.match(input.parameters.allowedProfiles[_], [], get_annotation_for(container, metadata))
        }

        input_containers[c] {
            c := input.review.object.spec.containers[_]
        }
        input_containers[c] {
            c := input.review.object.spec.initContainers[_]
        }
        input_containers[c] {
            c := input.review.object.spec.ephemeralContainers[_]
        }

        get_annotation_for(container, metadata) = out {
            out = metadata.annotations[sprintf("container.apparmor.security.beta.kubernetes.io/%v", [container.name])]
        }
        get_annotation_for(container, metadata) = out {
            not metadata.annotations[sprintf("container.apparmor.security.beta.kubernetes.io/%v", [container.name])]
            out = "runtime/default"
        }
